import requests
from urllib.parse import quote
import json
import folium
from typing import Optional, Dict, Any

class RecommendationService:
    def __init__(self):
        # Load API configurations
        self.api_config = {
            "openai_url": "https://api.gptsapi.net/v1",
            "openai_key": "sk-Nnm83576358bafced470371c05725c2e9a8dfb994c4NEhd4",
            "serpapi_key": "5f2b4bd965b1a6e802ba08af5fa625930a54ee235267426298c2f4cb04ed189a",
            "weather_key": "57dbc0b8c073126868e328d089d6db44"
        }
    
    def _get_weather_info(self, lat: float, lon: float) -> Optional[Dict]:
        """Fetch weather information for given coordinates"""
        base_url = "https://api.openweathermap.org/data/2.5/weather"
        params = {
            "lat": lat,
            "lon": lon,
            "appid": self.api_config["weather_key"],
            "units": "metric"
        }
        try:
            response = requests.get(base_url, params=params)
            return response.json() if response.status_code == 200 else None
        except requests.RequestException:
            return None

    def _fetch_search_results(self, query: str) -> Optional[Dict]:
        """Search for sports events using SERP API"""
        encoded_query = quote(query)
        url = f"https://serpapi.com/search.json?engine=google&q={encoded_query}&api_key={self.api_config['serpapi_key']}"
        try:
            response = requests.get(url, headers={"User-Agent": "Mozilla/5.0"}, timeout=10)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException:
            return None

    def _get_ai_recommendation(self, location_info: Dict, weather_info: Dict, 
                             search_query: str, search_results: Dict) -> Optional[str]:
        """Get AI-generated recommendations from OpenAI"""
        try:
            search_summary = []
            if search_results and 'organic_results' in search_results:
                for result in search_results['organic_results'][:5]:
                    search_summary.append(f"   - {result['title']}")
            
            prompt = f"""
            Generate recommendations based on the following information:
            1. Location: {location_info.get('city', 'Unknown city')}, {location_info.get('country_name', 'Unknown country')}
            2. Weather: {weather_info['weather'][0]['description']}, Temperature {weather_info['main']['temp']}°C, Humidity {weather_info['main']['humidity']}%
            3. User search query: {search_query}
            4. Reference search results:
            {chr(10).join(search_summary) if search_summary else '   - No valid search results'}
            
            Requirements:
            - Return a JSON response with "text" and "locations" fields
            - "text" field contains human-readable recommendations
            - "locations" field is an array where each element contains "name", "description", "latitude" and "longitude"
            - Prioritize recommendations with GPS coordinates
            - If no coordinates available, provide detailed addresses
            """
            
            payload = {
                "model": "gpt-4o-mini",
                "messages": [{"role": "user", "content": prompt}],
                "temperature": 0.7,
                "response_format": {"type": "json_object"}
            }

            headers = {
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_config['openai_key']}"
            }

            response = requests.post(
                self.api_config["openai_url"] + "/chat/completions",
                json=payload,
                headers=headers
            )
            response.raise_for_status()
            return response.json()["choices"][0]["message"]["content"]
        except Exception as e:
            print(f"OpenAI request error: {str(e)}")
            return None

    def generate_recommendation_map(self, user_location: Dict, recommendation_data: Dict) -> Optional[str]:
        """Generate interactive map with recommendations"""
        try:
            m = folium.Map(
                location=[user_location['latitude'], user_location['longitude']],
                zoom_start=12
            )
            
            folium.Marker(
                [user_location['latitude'], user_location['longitude']],
                popup=f"Your Location<br>{user_location.get('city', 'Unknown')}",
                icon=folium.Icon(color="blue")
            ).add_to(m)
            
            if 'locations' in recommendation_data:
                for place in recommendation_data['locations']:
                    folium.Marker(
                        [place['latitude'], place['longitude']],
                        popup=f"<b>{place['name']}</b><br>{place['description']}",
                        icon=folium.Icon(color="red")
                    ).add_to(m)
            
            filename = "recommendation_map.html"
            m.save(filename)
            return filename
        except Exception as e:
            print(f"Map generation error: {str(e)}")
            return None

    def get_recommendations(self, query: str, user_location: Dict = None) -> Dict[str, Any]:
        """Main method to get sports event recommendations"""
        if not user_location:
            try:
                location_resp = requests.get('https://freegeoip.app/json/')
                user_location = location_resp.json()
            except Exception as e:
                return {"error": f"Failed to get location: {str(e)}"}
        
        weather = self._get_weather_info(user_location['latitude'], user_location['longitude'])
        if not weather:
            return {"error": "Failed to get weather information"}
        
        search_results = self._fetch_search_results(query)
        if not search_results:
            return {"error": "Failed to get search results"}
        
        recommendation = self._get_ai_recommendation(
            user_location, weather, query, search_results
        )
        if not recommendation:
            return {"error": "Failed to generate recommendations"}
        
        try:
            rec_data = json.loads(recommendation)
            map_file = self.generate_recommendation_map(user_location, rec_data)
            
            return {
                "success": True,
                "data": rec_data,
                "user_location": {
                    "lat": user_location['latitude'],
                    "lng": user_location['longitude']
                },
                "map_file": map_file
            }
        except Exception as e:
            return {"error": f"Error processing recommendation data: {str(e)}"}